package Tool;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import standard.Standard;

import useTool.ThreadDoOtherThing;
import useTool.ThreadListener;

public class Client implements Linda{
	private Socket socket=null;
	private InputStream is=null;
	
	public Client()
	{
		try{
			socket=new Socket("127.0.0.1",8000);
		}catch(IOException e){
			e.printStackTrace();
		}		
	}
	
//	public void out(Object object,String name)
//	{ 
//		try{
//			ByteArrayOutputStream ByteForObject=new ByteArrayOutputStream();
//			ObjectOutputStream outStream=new ObjectOutputStream(ByteForObject);
//			outStream.writeObject(object);
//			byte[] data=ByteForObject.toByteArray();
//			
//			Standard standard=new Standard("out",name,data);	
//			ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
//			oos.writeObject(standard);
//		}catch(IOException e)
//		{
//			e.printStackTrace();
//		}
//	}
	
	public void out(String name, Object...objects)
	{
//		for(int float_index = 0;float_index<floats.length;float_index++)
//		{
			try
			{
				ByteArrayOutputStream ByteForObject = new ByteArrayOutputStream(); //catch the byte data
				ObjectOutputStream outStream = new ObjectOutputStream(ByteForObject); //means after serialization where to keep the serialized data
				outStream.writeObject(objects);
				byte[] data = ByteForObject.toByteArray();
				
				Standard standard = new Standard("out",name,data);
				ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
				oos.writeObject(standard);
			}catch(IOException e){
				e.printStackTrace();
			}
//		}
	}
		
	public Object in(String name)
	{
		try{
			Standard standard=new Standard("in",name);
			ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(standard);
			
		    is=socket.getInputStream();
			byte[] s=new byte[1024];
			int len2=is.read(s);
			ByteArrayInputStream TransferBackToS=new ByteArrayInputStream(s);
		    ObjectInputStream in2=new ObjectInputStream(TransferBackToS);
			Object object=(Object)in2.readObject();
			return object;
		}catch(IOException e){
			e.printStackTrace();
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		return null;
	}
	
	public Future<Object> inAsyn(String name)
	{
		Standard standard = null;
		Future<Object> object1=null;
		Object object = null;
		try{
			standard = new Standard("inAsyn",name);
			ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(standard);
			
			is = socket.getInputStream();
			byte[] s = new byte[1024];
			int len2 = is.read(s);
			ByteArrayInputStream  TransferBackToS = new ByteArrayInputStream(s); 
			ObjectInputStream in2 = new ObjectInputStream(TransferBackToS);
			Object return_object = (Object)in2.readObject();
			Standard return_standard = (Standard)return_object;
			System.out.println("For testing 1!!!!!!!!!");
			if(return_standard.getAnswer().equals("Not Exist Yet"))
			{
				System.out.println("For Testing 2!!!!!!!!!!!!!!!!");
				ExecutorService exec = Executors.newCachedThreadPool();
				ThreadListener listener = new ThreadListener(socket,name);
				object1 = exec.submit(listener);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}catch(ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		return object1;
	}
	
	public Future<Object> readAsyn(String name)
	{
		Standard standard = null;
		Future<Object> object1=null;
		Object object = null;
		try{
			standard = new Standard("readAsyn",name);
			ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(standard);
			
			is = socket.getInputStream();
			byte[] s = new byte[1024];
			int len2 = is.read(s);
			ByteArrayInputStream  TransferBackToS = new ByteArrayInputStream(s); 
			ObjectInputStream in2 = new ObjectInputStream(TransferBackToS);
			Object return_object = (Object)in2.readObject();
			Standard return_standard = (Standard)return_object;
			System.out.println("For testing 1!!!!!!!!!");
			if(return_standard.getAnswer().equals("Not Exist Yet"))
			{
				System.out.println("For Testing 2!!!!!!!!!!!!!!!!");
				ExecutorService exec = Executors.newCachedThreadPool();
				ThreadListener listener = new ThreadListener(socket,name);
				object1 = exec.submit(listener);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}catch(ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		return object1;
	}
	
	
	public Object read(String name)
	{
		try{
			Standard standard=new Standard("read",name);
			ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(standard);
			
			is=socket.getInputStream();
			byte[] s=new byte[1024];
			int len2=is.read(s);
			ByteArrayInputStream TransferBackToS=new ByteArrayInputStream(s);
		    ObjectInputStream in2=new ObjectInputStream(TransferBackToS);
			Object object=(Object)in2.readObject();
			return object;
		}catch(IOException e){
			e.printStackTrace();
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		return null;
	}
	
	public void close()
	{
		try{
			if(socket!=null)
			{
				this.socket.close();
			}
			if(is!=null)
			{
				this.is.close();
			}		
		}catch(IOException e){
			e.printStackTrace();
		}
		
	}
}
